﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using StockLib;
using StockLib.Indicator;
using StockUtil;

namespace StockControl
{
    public partial class StockKGraphControl : Control
    {
        const int X_MINOR_TICK_HEIGHT = 2;
        const int Y_MAJOR_TICK_WIDTH = 4;

        Rectangle rectGraph;
        Rectangle rectXAxis;
        Rectangle rectYAxis;

        private float _pointWidth = 1;
        public float pointWidth
        {
            get
            {
                return this._pointWidth;
            }
            set
            {
                this._pointWidth = value;

                kIndicator.pointWidth = value;
                foreach (StockIndicator indicator in otherIndicators)
                {
                    indicator.pointWidth = value;
                }
            }
        }

        private int _yAxisWidth;
        public int yAxisWidth
        {
            get
            {
                return this._yAxisWidth;
            }
            set
            {
                this._yAxisWidth = value;

                kIndicator.yAxisWidth = value;
                foreach (StockIndicator indicator in otherIndicators)
                {
                    indicator.yAxisWidth = value;
                }
            }
        }

        private int _xAxisHeight;
        public int xAxisHeight
        {
            get
            {
                return this._xAxisHeight;
            }
            set
            {
                this._xAxisHeight = value;

                kIndicator.xAxisHeight = value;
                foreach (StockIndicator indicator in otherIndicators)
                {
                    indicator.xAxisHeight = value;
                }
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            if (KData == null || KData.Count <= 0)
                return;

            using (Graphics g = CreateGraphics())
            {
                if (bitmapNewXAxis == null && bitmapNewYAxis == null && bitmapNewXCursor == null && bitmapNewYCursor == null)
                {
                    
                }
                else
                {
                    // 在原位置恢复位图
                    g.DrawImage(bitmapOldXAxis, locationLastXAxis);
                    g.DrawImage(bitmapOldYAxis, locationLastYAxis);
                    g.DrawImage(bitmapOldXCursor, locationLastXCursor);
                    g.DrawImage(bitmapOldYCursor, locationLastYCursor);
                }
            }


            MeasureSize(e.Graphics);

            if (e.ClipRectangle.IntersectsWith(rectXAxis))
            {
                DrawXAxis(e.Graphics);
            }

            if (e.ClipRectangle.IntersectsWith(ClientRectangle))
            {
                DrawGraph(e);
            }

            ShowAxis = true;
        }

        private void MeasureSize(Graphics g)
        {
            yAxisWidth = (int)(TextRenderer.MeasureText("01234.", Font).Width) + Y_MAJOR_TICK_WIDTH;
            xAxisHeight = (int)(TextRenderer.MeasureText("0123456789年月日", Font).Height * 1.2) + X_MINOR_TICK_HEIGHT;

            rectYAxis = ClientRectangle;
            rectYAxis.Width = yAxisWidth;
            rectYAxis.X = ClientRectangle.Right - yAxisWidth;
            g.DrawLine(StockProfile.Pens.AxisLinePen, rectYAxis.Left, rectYAxis.Top, rectYAxis.Left, rectYAxis.Bottom);

            rectXAxis = ClientRectangle;
            rectXAxis.Height = xAxisHeight;
            rectXAxis.Y = ClientRectangle.Bottom - xAxisHeight;
            g.DrawLine(StockProfile.Pens.AxisLinePen, rectXAxis.Left, rectXAxis.Top, rectXAxis.Right, rectXAxis.Top);

            rectGraph = ClientRectangle;
            rectGraph.Width -= yAxisWidth;
            rectGraph.Height -= xAxisHeight;

            rectYAxis.Height -= xAxisHeight;
            rectXAxis.Width -= yAxisWidth;

            pointWidth = GetXRatio();
        }

        private void DrawGraph(PaintEventArgs e)
        {
            float mainGraphRatio = 0.55f;

            Rectangle rect = ClientRectangle;
            rect.Height = (int)(rectGraph.Height * mainGraphRatio);
            kIndicator.stock = Stock;
            kIndicator.DrawGraph(e, rect);

            for (int i = 0; i < otherIndicators.Count; i++)
            {
                rect = ClientRectangle;
                rect.Height = (int)(rectGraph.Height * (1 - mainGraphRatio) / otherIndicators.Count);
                rect.Y = (int)(ClientRectangle.Top + rectGraph.Height * mainGraphRatio + i * rect.Height);
                otherIndicators[i].DrawGraph(e, rect);
            }
        }

        private void DrawXAxis(Graphics g)
        {
            const int minWith = 30;

            // 输出年份
            DateTime timeFirst = DateTimeHelper.FromGTime(KData[indexStart].Time);
            string txtYear = string.Format("{0}年", timeFirst.Year);
            Rectangle rectYear = new Rectangle();
            rectYear.Size = TextRenderer.MeasureText(txtYear, Font);
            rectYear.X = rectXAxis.X;
            rectYear.Y = rectXAxis.Y + X_MINOR_TICK_HEIGHT;

            int xPosLast = 0;
            DateTime timeLast = timeFirst;
            for (int i = indexStart; i <= indexEnd; i++)
            {
                int xPos = GetXPos(i);
                DateTime time = DateTimeHelper.FromGTime(KData[i].Time);
                if (timeLast.Month != time.Month)
                {
                    if (xPos - xPosLast >= minWith && xPos > rectYear.Right)
                    {
                        g.DrawLine(StockProfile.Pens.AxisLinePen, xPos, rectXAxis.Y, xPos, rectXAxis.Bottom);

                        if (xPosLast > 0)
                        {
                            for (int j = 1; j <= 3; j++)
                            {
                                int xPosMinor = xPosLast + (xPos - xPosLast) * j / 4;
                                g.DrawLine(StockProfile.Pens.AxisLinePen, xPosMinor, rectXAxis.Y, xPosMinor, rectXAxis.Y + X_MINOR_TICK_HEIGHT);
                            }
                        }

                        string text = string.Format("{0}", time.Month);
                        Size sizeText = TextRenderer.MeasureText(g, text, Font);
                        if (xPos + sizeText.Width <= rectXAxis.Right)
                        {
                            TextRenderer.DrawText(g, text, Font, new Point(xPos, rectXAxis.Y + X_MINOR_TICK_HEIGHT), StockProfile.Colors.AxisTextColor);
                        }

                        if (xPosLast <= 0)
                        {
                            txtYear = string.Format("{0}年", time.Year);
                        }

                        xPosLast = xPos;
                    }
                }
                timeLast = time;
            }

            TextRenderer.DrawText(g, txtYear, Font, rectYear, StockProfile.Colors.AxisTextColor, TextFormatFlags.VerticalCenter | TextFormatFlags.Left);
        }

        protected int GetXIndex(int xPos)
        {
            float index = (xPos - rectXAxis.Left) / _pointWidth + 0.5f + indexStart - 1;
            return (int)index;
        }

        private int GetXPos(int index)
        {
            float xPos = _pointWidth * (index + 1 - indexStart) + rectXAxis.Left;
            return (int)xPos;
        }

        private float GetXRatio()
        {
            int showDays = (indexEnd - indexStart + 2);
            if (showDays < MIN_DAYS + 2)
                showDays = MIN_DAYS + 2;

            float xRatio = 1.0f * (rectXAxis.Width) / showDays;
            return xRatio;
        }
    }
}
